package router

import (
	"admin-system-go/model"
	"admin-system-go/model/dto"
	"admin-system-go/service"
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

type UserRouter struct {
	userService service.UserService
	r           *gin.Engine
}

func NewUserRouter() UserRouter {
	return UserRouter{userService: service.GetUserService()}
}

func (userRouter UserRouter) Register(r *gin.Engine) {
	userRouter.r = r
	r.POST(apiVersion+"/user/register", userRouter.registerUser())
	r.POST(apiVersion+"/user/password/change", userRouter.changeUserPassword())
	r.POST(apiVersion+"/user/login", userRouter.login())
	r.POST(apiVersion+"/user/update", userRouter.updateUser())
	r.DELETE(apiVersion+"/user/delete", userRouter.deleteUser())
	r.GET(apiVersion+"/user/list", userRouter.queryUser())
	r.GET(apiVersion+"/user/current", userRouter.getCurrentUser())
	r.POST(apiVersion+"/user/add/group", userRouter.AddToGroup())
}

func (userRouter UserRouter) login() gin.HandlerFunc {
	return func(context *gin.Context) {
		var loginDto dto.LoginDTO
		err := context.ShouldBind(&loginDto)
		if err != nil {
			context.JSON(http.StatusOK, model.ParamErrorModel)
			return
		}
		loginResult := userRouter.userService.Login(loginDto)
		if loginResult.Success {
			//session
			uid := loginResult.Data.(uint)
			uidStr := fmt.Sprintf("%d", uid)
			session := sessions.Default(context)
			session.Delete(uidStr)
			userRouter.userService.RemoveToken(uid)
			newToken := userRouter.userService.CreateToken(uid, time.Now().Add(time.Minute*60))
			session.Set(uidStr, newToken)
			session.Set("uid", uidStr)
			err := session.Save()
			if err != nil {
				fmt.Println(err)
			}
		}
		context.JSON(http.StatusOK, loginResult)
	}
}

func (userRouter UserRouter) registerUser() gin.HandlerFunc {
	return func(context *gin.Context) {
		var userAddDTO dto.UserAddDTO
		err := context.ShouldBind(&userAddDTO)
		if err != nil {
			context.JSON(http.StatusOK, model.ParamErrorModel)
			return
		}
		context.JSON(http.StatusOK, userRouter.userService.RegisterUser(userAddDTO))
	}
}

func (userRouter UserRouter) changeUserPassword() gin.HandlerFunc {
	return func(context *gin.Context) {
		var changPasswordDTO dto.ChangPasswordDTO
		err := context.ShouldBind(&changPasswordDTO)
		if err != nil {
			context.JSON(http.StatusOK, model.ParamErrorModel)
			return
		}
		context.JSON(http.StatusOK, userRouter.userService.ChangeUserPassword(changPasswordDTO))
	}
}

func (userRouter UserRouter) updateUser() gin.HandlerFunc {
	return func(context *gin.Context) {
		var updateDTO dto.UserUpdateDTO
		err := context.ShouldBind(&updateDTO)
		if err != nil {
			context.JSON(http.StatusOK, model.ParamErrorModel)
			return
		}
		context.JSON(http.StatusOK, userRouter.userService.UpdateUser(updateDTO))
	}
}

func (userRouter UserRouter) deleteUser() gin.HandlerFunc {
	return func(context *gin.Context) {
		var userDelDTO dto.UserDelDTO = dto.UserDelDTO{Ids: make([]string, 0)}
		err := context.ShouldBind(&userDelDTO)
		if err != nil {
			fmt.Println(err)
			context.JSON(http.StatusOK, model.ParamErrorModel)
			return
		}
		context.JSON(http.StatusOK, userRouter.userService.DeleteUser(userDelDTO))
	}
}

func (userRouter UserRouter) queryUser() gin.HandlerFunc {
	return func(context *gin.Context) {
		var userQueryDTO dto.UserQueryDTO
		err := context.BindQuery(&userQueryDTO)
		if err != nil {
			context.JSON(http.StatusOK, model.ParamErrorModel)
			return
		}
		uid := GetCurrentUid(context)
		userQueryDTO.Uid = uid
		context.JSON(http.StatusOK, userRouter.userService.QueryUser(userQueryDTO))
	}
}

func (userRouter UserRouter) getCurrentUser() gin.HandlerFunc {
	return func(context *gin.Context) {
		uid := GetCurrentUid(context)
		context.JSON(http.StatusOK, userRouter.userService.GetUserById(uid))
	}
}

func (userRouter UserRouter) AddToGroup() gin.HandlerFunc {
	return func(context *gin.Context) {
		var userAddGroup dto.UserAddGroupDTO
		err := context.ShouldBind(&userAddGroup)
		if err != nil {
			context.JSON(http.StatusOK, model.ParamErrorModel)
			return
		}
		context.JSON(http.StatusOK, userRouter.userService.AddUserToGroup(userAddGroup))
	}
}
